home *** CD-ROM | disk | FTP | other *** search
/ Internet Surfer 2.0 / Internet Surfer 2.0 (Wayzata Technology) (1996).iso / pc / text / mac / faqs.380 < prev    next >
Encoding:
Text File  |  1996-02-12  |  27.7 KB  |  757 lines

  1. Frequently Asked Questions (FAQS);faqs.380
  2.  
  3.  
  4.  */
  5.  
  6. /* text_entry.c -- This demo shows how the RowColumn widget can be
  7.  * configured to build a text entry form.  It displays a table of
  8.  * right-justified Labels and Text widgets that extend to the right
  9.  * edge of the Form.
  10.  */
  11. #include <Xm/LabelG.h>
  12. #include <Xm/RowColumn.h>
  13. #include <Xm/Text.h>
  14.  
  15. char *text_labels[] = {
  16.     "Name:", "Phone:", "Address:", "City:", "State:", "Zip:",
  17. };
  18.  
  19. main(argc, argv)
  20. int argc;
  21. char *argv[];
  22. {
  23.     Widget toplevel, rowcol;
  24.     XtAppContext app;
  25.     char buf[8];
  26.     int i;
  27.  
  28.     toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
  29.         &argc, argv, NULL, NULL);
  30.  
  31.     rowcol = XtVaCreateWidget("rowcolumn",
  32.         xmRowColumnWidgetClass, toplevel,
  33.         XmNpacking,        XmPACK_COLUMN,
  34.         XmNnumColumns,     XtNumber(text_labels),
  35.         XmNorientation,    XmHORIZONTAL,
  36.         XmNisAligned,      True,
  37.         XmNentryAlignment, XmALIGNMENT_END,
  38.         NULL);
  39.  
  40.     /* simply loop thru the strings creating a widget for each one */
  41.     for (i = 0; i < XtNumber(text_labels); i++) {
  42.         XtVaCreateManagedWidget(text_labels[i],
  43.             xmLabelGadgetClass, rowcol,
  44.             NULL);
  45.         sprintf(buf, "text_%d", i);
  46.         XtVaCreateManagedWidget(buf,
  47.             xmTextWidgetClass, rowcol,
  48.             NULL);
  49.     }
  50.  
  51.     XtManageChild(rowcol);
  52.     XtRealizeWidget(toplevel);
  53.     XtAppMainLoop(app);
  54. }
  55.  
  56. This makes all objects exactly the same size.  It does not resize in nice
  57. ways.
  58.  
  59. If you want the text widgets lined up on the left, and the labels to be the
  60. size of the longest string, resizing nicely both horizontally and vertically,
  61. as in
  62.  
  63.          -------------------------------------
  64.         |                    ---------------- |
  65.         |          a label  |Some text       ||
  66.         |                    ---------------- |
  67.                              ---------------- |
  68.         |   a longer label  |Some more text  ||
  69.         |                    ---------------- |
  70.         |                    ---------------- |
  71.         |a very long label  |Even more text  ||
  72.         |                    ---------------- |
  73.          -------------------------------------
  74.  
  75.  
  76.  
  77. Answer: Do this: to get the widgets lined up horizontally, use a form but
  78. place the widgets using XmATTACH_POSITION.  In the example, attach the top of
  79. the first label to the form, the bottomPosition to 33 (33% of the height).
  80. Attach the topPosition of the second label to 33 and the bottomPosition to 66.
  81. Attach the topPosition of the third label to 66 and the bottom of the label to
  82. the form.  Do the same with the text widgets.
  83.  
  84. To get the label widgets lined up vertically, use the right attachment of
  85. XmATTACH_OPPOSITE_WIDGET: starting from the one with the longest label, attach
  86. widgets on the right to each other. In the example, attach the 2nd label to
  87. the third, and the first to the second.  To get the text widgets lined up,
  88. just attach them on the left to the labels.  To get the text in the labels
  89. aligned correctly, use XmALIGNMENT_END for the XmNalignment resource.
  90.  
  91.         /* geometry for label 2
  92.         */
  93.         n = 0;
  94.         XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  95.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  96.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  97.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  98.         XtSetArg (args[n], XmNtopPosition, 66); n++;
  99.         XtSetValues (label[2], args, n);
  100.  
  101.         /* geometry for label 1
  102.         */
  103.         n = 0;
  104.         XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  105.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  106.         XtSetArg (args[n], XmNbottomPosition, 66); n++;
  107.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  108.         XtSetArg (args[n], XmNtopPosition, 33); n++;
  109.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  110.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  111.         XtSetArg (args[n], XmNrightWidget, label[2]); n++;
  112.         XtSetValues (label[1], args, n);
  113.  
  114.         /* geometry for label 0
  115.         */
  116.         n = 0;
  117.         XtSetArg (args[n], XmNalignment, XmALIGNMENT_END); n++;
  118.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  119.         XtSetArg (args[n], XmNbottomPosition, 33); n++;
  120.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  121.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  122.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
  123.         XtSetArg (args[n], XmNrightWidget, label[1]); n++;
  124.         XtSetValues (label[0], args, n);
  125.  
  126.         /* geometry for text 0
  127.         */
  128.         n = 0;
  129.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  130.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  131.         XtSetArg (args[n], XmNbottomPosition, 33); n++;
  132.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  133.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  134.         XtSetArg (args[n], XmNleftWidget, label[0]); n++;
  135.         XtSetValues (text[0], args, n);
  136.  
  137.         /* geometry for text 1
  138.         */
  139.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  140.         XtSetArg (args[n], XmNtopPosition, 33); n++;
  141.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
  142.         XtSetArg (args[n], XmNbottomPosition, 66); n++;
  143.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  144.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  145.         XtSetArg (args[n], XmNleftWidget, label[1]); n++;
  146.         XtSetValues (text[1], args, n);
  147.  
  148.         /* geometry for text 2
  149.         */
  150.         XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
  151.         XtSetArg (args[n], XmNtopPosition, 66); n++;
  152.         XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  153.         XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
  154.         XtSetArg (args[n], XmNleftWidget, label[2]); n++;
  155.         XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  156.         XtSetValues (text[2], args, n);
  157.  
  158.  
  159. -----------------------------------------------------------------------------
  160. Subject: 61) TOPIC: PUSHBUTTON WIDGET
  161.  
  162. -----------------------------------------------------------------------------
  163. Subject: 62) Why can't I use accelerators on buttons not in a menu?
  164.  
  165. Answer: It is apparently a difficult feature to implement, but OSF are
  166. considering this for the future. It is problematic trying to use the Xt
  167. accelerators since the Motif method interferes with this.  The workaround
  168. suggested so far is to duplicate your non-menu button by a button in a menu
  169. somewhere, which does have a menu-accelerator installed.  When the user
  170. invokes what they think is the accelerator for the button they can see Motif
  171. actually invokes the button on the menu that they can't see at the time.
  172.  
  173.  
  174. -----------------------------------------------------------------------------
  175. Subject: 63) TOPIC: LABEL WIDGET
  176.  
  177. -----------------------------------------------------------------------------
  178. Subject: 64) How can I align the text in a label (button, etc) widget?
  179.  
  180. Answer: The alignment for the label widget is controlled by the resource
  181. XmNalignment, and the default centers the text. Use this resource to change it
  182. to left or right alignment.  However, when the label (or any descendant) is in
  183. a row column, and XmNisAligned is True (the default), the row column aligns
  184. text using its resource XmNentryAlignment. If you want simultaneous control
  185. over all widgets use this, but otherwise turn XmNisAligned off and do it
  186. individually.
  187.  
  188.  
  189.  
  190. -----------------------------------------------------------------------------
  191. Subject: 65) Why doesn't label alignment work in a RowColumn?
  192.  
  193. Answer: RowColumn has a  resource XmNisAligned (default True) and and
  194. XmNentryAlignment (default XmALIGNMENT_BEGINNING).  These control alignment of
  195. the labelString in Labels and descendants. Set XmNisAligned to False to turn
  196. this off.
  197.  
  198. -----------------------------------------------------------------------------
  199. Subject: 66)  How can I set a multiline label?
  200. [Last modified: September 92]
  201.  
  202. Answer: In .Xdefaults
  203.  
  204.       *XmLabel*labelString:             Here\nis\nthe\nLabel
  205.  
  206. This method does not seem to work in some of the older Motif 1.0 versions.
  207.  
  208. In code,
  209.  
  210.       char buf[128];
  211.       XmString msg;
  212.       sprintf(buf, "Here\nis\nthe\nLabel");
  213.       msg = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
  214.       XtSetArg (args[n], XmNlabelString, msg);
  215.  
  216. Gives a four line label, using the escape sequence \n for a newline.  However,
  217. XmStringCreateLtoR() is obsoleted from version 1.1 on, and may disappear.
  218. This is because it it is only in the AES as "trial-use" and has been proposed
  219. for removal from the AES. Realistically, it will probably not be removed from
  220. any backward compatible versions of Motif, but the potential is there.  If it
  221. does disappear (or if you want to avoid using the non-AES compliant
  222. XmSTRING_DEFAULT_CHARSET), try this from Jean-Philippe Martin-Flatin
  223. <syj@ecmwf.co.uk>
  224.  
  225. #include <Xm/Xm.h>
  226. #include <string.h>
  227.  
  228. /*-----------------------------------------------------
  229.     Create a new XmString from a char*
  230.  
  231.     This function can deal with embedded 'newline' and
  232.     is equivalent to the obsolete XmStringCreateLtoR,
  233.     except it does not use non AES compliant charset
  234.     XmSTRING_DEFAULT_CHARSET
  235. ----------------------------------------------------*/
  236. XmString xec_NewString(char *s)
  237. {
  238.     XmString xms1;
  239.     XmString xms2;
  240.     XmString line;
  241.     XmString separator;
  242.     char     *p;
  243.     char     *t = XtNewString(s);   /* Make a copy for strtok not to */
  244.                                     /* damage the original string    */
  245.  
  246.  
  247.     separator = XmStringSeparatorCreate();
  248.     p         = strtok(t,"\n");
  249.     xms1      = XmStringCreateSimple(p);
  250.  
  251.     while (p = strtok(NULL,"\n"))
  252.     {
  253.         line = XmStringCreateSimple(p);
  254.         xms2 = XmStringConcat(xms1,separator);
  255.         XmStringFree(xms1);
  256.         xms1 = XmStringConcat(xms2,line);
  257.         XmStringFree(xms2);
  258.         XmStringFree(line);
  259.     }
  260.  
  261.     XmStringFree(separator);
  262.     XtFree(t);
  263.     return xms1;
  264. }
  265.  
  266.  
  267. Do not use XmStringCreateSimple() - it does not process the newline character
  268. in the way you want.
  269.  
  270. In UIL, you have to explicitly create a compound string with a separator.
  271. Here's what W. Scott Meeks suggests:
  272.  
  273. value nl : compound_string('', seperate=true);
  274.  
  275. object my_label : XmLabel
  276. {
  277.     arguments
  278.     {
  279.         XmNlabelString = 'Here' & nl & 'is' & nl & 'the' & nl & 'Label';
  280.     };
  281. };
  282.  
  283.  
  284. -----------------------------------------------------------------------------
  285. Subject: 67)  How can I have a vertical label?
  286.  
  287. Answer: Make a multiline label with one character per line, as in the last
  288. question. There is no way to make the text rotated by 90 degrees though.
  289.  
  290.  
  291. -----------------------------------------------------------------------------
  292. Subject: 68)  How can I have a Pixmap in a Label?
  293.  
  294. Answer: From Bob Hays (bobhays@spss.com)
  295.  
  296.     Pixmap px_disarm, px_disarm_insens;
  297.  
  298.     Widget Label1;
  299.     Pixel   foreground, background;
  300.     Arg     args[4];
  301.     Arg     arg[] = {
  302.                 { XmNforeground, &foreground },
  303.                 { XmNbackground, &background }
  304.     };
  305.  
  306.     Label1 = XmCreateLabel ( Shell1, "Label1",
  307.                                        (Arg *) NULL, (Cardinal) 0 );
  308.     XtGetValues ( Label1, arg, XtNumber ( arg ) );
  309.     px_disarm =
  310.       XCreatePixmapFromBitmapData(display,
  311.                                 DefaultRootWindow(display),
  312.                                 mtn_bits, mtn_width, mtn_height,
  313.                                 foreground,
  314.                                 background,
  315.                                 DefaultDepth(display,DefaultScreen(display)));
  316.     px_disarm_insens =
  317.       XCreatePixmapFromBitmapData(display,
  318.                                 DefaultRootWindow(display),
  319.                                 mtn_ins_bits, mtn_ins_width, mtn_ins_height,
  320.                                 foreground,
  321.                                 background,
  322.                                 DefaultDepth(display,DefaultScreen(display)));
  323.  
  324.     n = 0;
  325.     XtSetArg(args[n], XmNlabelType, XmPIXMAP);  n++;
  326.     XtSetArg(args[n], XmNlabelPixmap, px_disarm);  n++;
  327.     XtSetArg(args[n], XmNlabelInsensitivePixmap, px_disarm_insens ); n++;
  328.     XtSetValues ( Label1, args, n );
  329.     XtManageChild(Label1);
  330.  
  331. That will cause the foreground and background of your pixmap to be inherited
  332. from the one that would be used by OSF/Motif when the label is displayed.  The
  333. advantage is that this will utilize any resource values the user may have
  334. requested without looking explicitly into the resource database.  And, you
  335. will have a pixmap handy if the application insensitizes the label (without an
  336. XmNlabelInsensitivePixmap your label will go empty if made insensitive).
  337.  
  338. [Bob's original code was for a PushButton. Just change all Label to PushButton
  339. for them.]
  340.  
  341.  
  342. -----------------------------------------------------------------------------
  343. Subject: 69) TOPIC: DRAWING AREA WIDGET
  344.  
  345. -----------------------------------------------------------------------------
  346. Subject: 70) How can I send an expose event to a Drawing Area widget?  (or any
  347. other, come to that). I want to send an expose event so that it will redraw
  348. itself.
  349.  
  350. Answer: Use the Xlib call
  351.  
  352.         XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0, True)
  353.  
  354. This clears the widget's window and generates an expose event in doing so.
  355. The widgets expose action will then redraw it.  This uses a round trip
  356. request.  An alternative, without the round trip is
  357.  
  358. from orca!mesa!rthomson@uunet.uu.net  (Rich Thomson):
  359.  
  360.     Widget da;
  361.     XmDrawingAreaCallbackStruct da_struct;
  362.  
  363.     da_struct.reason = XmCR_EXPOSE;
  364.     da_struct.event = (XEvent *) NULL;
  365.     da_struct.window = XtWindow(da);
  366.  
  367.     XtCallCallbacks(da, XmNexposeCallback, (XtPointer) da_struct);
  368.  
  369.  
  370. -----------------------------------------------------------------------------
  371. Subject: 71) How can I know when a DrawingArea has been resized?  It generates
  372. an expose event whn it is enlarged, but not when it is shrunk.
  373.  
  374. Answer: Use the resize callback.
  375.  
  376. -----------------------------------------------------------------------------
  377. Subject: 72) TOPIC: MENUS
  378.  
  379. -----------------------------------------------------------------------------
  380. Subject: 73) What can I put inside a menu bar?
  381.  
  382. Answer: You can only put cascade buttons in menu bars. No pushbuttons, toggle
  383. buttons or gadgets are allowed. When you create a pulldown menu with parent a
  384. menu bar, its real parent is a shell widget.
  385.  
  386. -----------------------------------------------------------------------------
  387. Subject: 74) Can I have a cascade button without a submenu in a pulldown menu?
  388.  
  389. Answer: Yes you can. A cascade button has an activate callback which is called
  390. when you click on it and it doesn't have a submenu. It can have a mnemonic,
  391. but keyboard traversal using the arrow keys in the menu will skip over it.
  392.  
  393. -----------------------------------------------------------------------------
  394. Subject: 75) Should I have a cascade button without a submenu in a pulldown
  395. menu?
  396.  
  397. Answer: No. This is forbidden by the style guide. Technically you can do it
  398. (see previous question) but if you do it will not be Motif style compliant.
  399. This is unlikely to change - if a "button" is important enough to be in a
  400. pulldown menu bar with no pulldown, it should be a button elsewhere.  (Mind
  401. you, you won't be able to put accelerators on it elsewhere though.)
  402.  
  403. -----------------------------------------------------------------------------
  404. Subject: 76)  What is the best way to create popup menus?
  405. [Last modified: August 92]
  406.  
  407. Susan Murdock Thompson (from OSF): In general, create a popupMenu as the child
  408. from which you will be posting it from (ie: if you have a bulletinBoard with a
  409. PushButton in it and want MB2 on the pushButton to post the popupMenu, create
  410. the popupMenu as a child of the pushButton).  [This parent-child relationship
  411. seems to make a big difference in the behavior of the popups.]  Add an event
  412. handler to handle buttonPress events.  You'll need to check for the correct
  413. button (what you've specified menuPost to be) before posting the menu.
  414.  
  415. To create a popup that can be accessible from within an entire client window,
  416. create it as the child of the top-most widget (but not the shell) and add
  417. event handlers for the top-most widget and children widgets.
  418.  
  419. ie:
  420.  
  421. {
  422.   ....
  423.  
  424.   XtManageChild(rc=XmCreateRowColumn(Shell1, "rc", NULL, 0));
  425.   XtManageChild(label = XmCreateLabel(rc, "label", NULL, 0));
  426.   XtManageChild(text = XmCreateText(rc, "text", NULL, 0));
  427.   XtManageChild(pushbutton = XmCreatePushButton(rc, "pushbutton", NULL, 0));
  428.  
  429.   n = 0;
  430.   XtSetArg(args[n], XmNmenuPost, "<Btn3Down>"); n++;
  431.   popup = XmCreatePopupMenu(rc, "popup", args, n);
  432.  
  433.   XtAddEventHandler(rc, ButtonPressMask, False, PostMenu3, popup);
  434.   XtAddEventHandler(text, ButtonPressMask, False, PostMenu3, popup);
  435.   XtAddEventHandler(label, ButtonPressMask, False, PostMenu3, popup);
  436.   XtAddEventHandler(pushbutton, ButtonPressMask, False, PostMenu3, popup);
  437.  
  438.   XtManageChild(m1 = XmCreatePushButton(popup, "m1", NULL, 0));
  439.   XtManageChild(m2 = XmCreatePushButton(popup, "m2", NULL, 0));
  440.   XtManageChild(m3 = XmCreatePushButton(popup, "m3", NULL, 0));
  441.  
  442.   XtAddCallback(m1, XmNactivateCallback, SayCB, "button M1");
  443.   XtAddCallback(m2, XmNactivateCallback, SayCB, "button M2");
  444.   XtAddCallback(m3, XmNactivateCallback, SayCB, "button M3");
  445.   ...
  446. }
  447.  
  448. /* where PostMenu3 is ... */
  449.  
  450. PostMenu3 (w, popup, event)
  451. Widget w;
  452. Widget popup;
  453. XButtonEvent * event;
  454. {
  455.   printf("menuPost = 3, button %d0, event->button);
  456.  
  457.   if (event->button != Button3)
  458.     return;
  459.   XmMenuPosition(popup, event);
  460.   XtManageChild(popup);
  461. }
  462.  
  463.  
  464.  
  465. -----------------------------------------------------------------------------
  466. Subject: 77)  How do popup menus work?
  467. [Last modified: August 92]
  468.  
  469. Answer:
  470.  
  471. When a popup menu is created as the child of a widget the menu system installs
  472. a translation on the parent of the popup and descendants with an action which:
  473. (1) when 3-rd button (the default for the menuPost resource) is pressed the
  474. cursor changes and the mouse is grabbed for 5 seconds; (2) disables event
  475. handlers on the descendants and the handlers are never called; (3) an event
  476. handler installed on the parent works fine.
  477.  
  478. It is done so that the correct event handler will (in fact) be called.  There
  479. is a grab with owner_events true.  The grab is released by a timer,  but
  480. normally the posted menu shell puts up it's own grab.
  481.  
  482. If you only have widgets then you can use the subwindow field in the event to
  483. identify the original widget.  If you have gadgets or other data that you want
  484. to change the menu for (or use a specific menu for) then you must do a walk of
  485. the parent's children to find the best match.
  486.  
  487. One thing to beware of is that even with the grab,  because the menu system
  488. does a grab with owner events true, you must either have an event handler, or
  489. nothing that will use the event on each widget in the hierarchy of the menu's
  490. parent.  If a child widget has another event handler for button down, it may
  491. swallow the event and do something else.
  492.  
  493.  
  494.  
  495. -----------------------------------------------------------------------------
  496. Subject: 78)  Should I use translation tables or actions for popup menus?
  497. [Last modified: August 92]
  498.  
  499. Answer: The original goal of popupMenus was that the user would not have to
  500. specify an event handler to manage popupMenus; however, that did not become
  501. reality.  Larry Rogers wrote:
  502.  
  503. > There appear to be two ways to manage popup menus.  I
  504. > am curious what the correct way would be:
  505.  
  506. > 1.  Change the translation table of the widget with the
  507. >    popup child to popup the menu.  Note that this does
  508. >    not currently working for many widgets, because aug-
  509. >    menting their translations, even for augment breaks
  510. >    the widget.
  511.  
  512. > 2.  Add an event handler at creation to the widget; then
  513. >    determine if the event that caused the event handler
  514. >    to be called is the current button being used by the
  515. >    menu as its activation button.
  516.  
  517. Susan Murdock Thompson (from OSF) replied: *Theoretically, you should be able
  518. to do both.*  Our documentation says use event handlers.  Our tests for the
  519. toolkit use event handlers and for UIL use translations.  (Although I tried an
  520. event handler with a UIL test and it works).
  521.  
  522. -----------------------------------------------------------------------------
  523. Subject: 79)  What are the known bugs in popup menus?
  524. [Last modified: August 92]
  525.  
  526. Answer: As at Motif 1.1.4, the bugs for which an OSF PIR exists are:
  527.  
  528.    (3)  Menus not being sticky (ie: posted on a Btn CLICK)  [ Note:this
  529.         problem occurs with OptionMenus as well]  (PIR 3435)
  530.  
  531.    (6)  Destroying a widget with an associated popupMenu results in
  532.         "Warning: Attempt to remove non-existant passive grab"         (PIR
  533. 2972)
  534.  
  535.    (7)  Current documentation insufficient regarding requirements for
  536.         success in using PopupMenus.  (PIR 3433)
  537.  
  538.  
  539. -----------------------------------------------------------------------------
  540. Subject: 80)  Can I have multiple popup menus on the same widget?
  541. [Last modified: August 92]
  542.  
  543. Answer: If you want to have several popups (activated by different mouse
  544. buttons) on the same widget..., well, that doesn't work yet.
  545.  
  546. If you want to have several popups on different children... that works.  But
  547. don't put a popup on the parent (manager) widget, or it will rule!
  548.  
  549.  
  550.  
  551. -----------------------------------------------------------------------------
  552. Subject: 81) TOPIC: INPUT FOCUS
  553.  
  554. -----------------------------------------------------------------------------
  555. Subject: 82) How can I direct the keyboard input to a particular widget?
  556.  
  557. Answer: In Motif 1.1 call XmProcessTraversal(target, XmTRAVERSE_CURRENT).  The
  558. widget (and all of its ancestors) does need to be realized BEFORE you call
  559. this. Otherwise it has no effect.  XmProcessTraversal is reported to have many
  560. bugs, so it may not work right.  A common occurrence is that it doesn't move
  561. to the widget, but if you call XmProcessTraversal *twice* in a row, it will.
  562. If you can't get it to work, try this from Kee Hinckley:
  563.  
  564.     // This insane sequence is as follows:
  565.     //      On manage set up a focus callback
  566.     //      On focus callback set up a timer (and get rid of focus callback!)
  567.     //      On timer set the focus (which only works if the parent
  568.     //      has the focus,
  569.     //      which is why we went through all of this garbage)
  570.     // There may be a better way, but I haven't time to try it now.
  571.     //
  572.     static void focusTO(void *data, XtIntervalId *) {
  573.         XmProcessTraversal((Widget) data, XmTRAVERSE_CURRENT);
  574.     }
  575.  
  576.     static void focusCB(Widget w, XtPointer data, XtPointer) {
  577.         XtRemoveCallback(w, XmNfocusCallback, focusCB, data);
  578.         XtAppAddTimeOut(XtWidgetToApplicationContext(w), 0, focusTO, data);
  579.     }
  580.  
  581.     void OmXSetFocus(Widget parent, Widget w) {
  582.         XtAddCallback(parent, XmNfocusCallback, focusCB, w);
  583.     }
  584.  
  585.  
  586. In Motif 1.0 call the undocumented _XmGrabTheFocus(target).
  587.  
  588. Do not use the X or Xt calls such as XtSetKeyboardFocus since this bypasses
  589. the Motif traversal layer and can cause it to get confused.  This can lead to
  590. odd keyboard behaviour elsewhere in your application.
  591.  
  592. -----------------------------------------------------------------------------
  593. Subject: 83)  How can I have a modal dialog which has to be answered before
  594. the application can continue?
  595. [Last modified: July 92]
  596.  
  597. Answer: The answer depends on whether you are using the Motif window manager
  598. mwm or not.  Test for this by XmIsMotifWMRunning.
  599.  
  600. The window manager mwm knows how to control event passing to dialog widgets
  601. declared as modal. If the dialog is set to application modal, then no
  602. interaction with the rest of the application can occur until the dialog is
  603. destroyed or unmanaged.
  604.  
  605. Use the appropriate code in the following program.  There is followup
  606. discussion after the program.
  607.  
  608.  
  609. /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
  610.  * This program is freely distributable without licensing fees and
  611.  * is provided without guarantee or warranty expressed or implied.
  612.  * This program is -not- in the public domain.  This program is
  613.  * taken from the Motif Programming Manual, O'Reilly Volume 6.
  614.  */
  615.  
  616. /*
  617.  * ask_user.c -- create a pushbutton that posts a dialog box
  618.  * that asks the user a question that requires an immediate
  619.  * response.  The function that asks the question actually
  620.  * posts the dialog that displays the question, waits for and
  621.  * returns the result.
  622.  */
  623. #include <X11/Intrinsic.h>
  624. #include <Xm/DialogS.h>
  625. #include <Xm/SelectioB.h>
  626. #include <Xm/RowColumn.h>
  627. #include <Xm/MessageB.h>
  628. #include <Xm/PushBG.h>
  629. #include <Xm/PushB.h>
  630.  
  631. XtAppContext app;
  632.  
  633. #define YES 1
  634. #define NO  2
  635.  
  636. /* main() --create a pushbutton whose callback pops up a dialog box */
  637. main(argc, argv)
  638. char *argv[];
  639. int argc;
  640. {
  641.     Widget parent, button, toplevel;
  642.     XmString label;
  643.     void pushed();
  644.  
  645.     toplevel = XtAppInitialize(&app, "Demos",
  646.         NULL, 0, &argc, argv, NULL, NULL, 0);
  647.  
  648.     label = XmStringCreateSimple("/bin/rm *");
  649.     button = XtVaCreateManagedWidget("button",
  650.         xmPushButtonWidgetClass, toplevel,
  651.         XmNlabelString,          label,
  652.         NULL);
  653.     XtAddCallback(button, XmNactivateCallback,
  654.         pushed, "Remove Everything?");
  655.     XmStringFree(label);
  656.  
  657.     XtRealizeWidget(toplevel);
  658.     XtAppMainLoop(app);
  659. }
  660.  
  661. /* pushed() --the callback routine for the main app's pushbutton. */
  662. void
  663. pushed(w, question)
  664. Widget w;
  665. char *question;
  666. {
  667.     if (AskUser(w, question) == YES)
  668.         puts("Yes");
  669.     else
  670.         puts("No");
  671. }
  672.  
  673. /*
  674.  * AskUser() -- a generalized routine that asks the user a question
  675.  * and returns the response.
  676.  */
  677. AskUser(parent, question)
  678. char *question;
  679. {
  680.     static Widget dialog;
  681.     XmString text, yes, no;
  682.     static int answer;
  683.     extern void response();
  684.  
  685.     answer = 0;
  686.     if (!dialog) {
  687.         dialog = XmCreateQuestionDialog(parent, "dialog", NULL, 0);
  688.         yes = XmStringCreateSimple("Yes");
  689.         no = XmStringCreateSimple("No");
  690.         XtVaSetValues(dialog,
  691.             XmNdialogStyle,        XmDIALOG_APPLICATION_MODAL,
  692.             XmNokLabelString,      yes,
  693.             XmNcancelLabelString,  no,
  694.             NULL);
  695.         XtSetSensitive(
  696.             XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON), False);
  697.         XtAddCallback(dialog, XmNokCallback, response, &answer);
  698.         XtAddCallback(dialog, XmNcancelCallback, response, &answer);
  699.         /* if the user interacts via the system menu: */
  700.         XtAddCallback(dialog, XmNpopdownCallback, response, &answer);
  701.     }
  702.     text = XmStringCreateSimple(question);
  703.     XtVaSetValues(dialog,
  704.         XmNmessageString,      text,
  705.         NULL);
  706.     XmStringFree(text);
  707.     XtManageChild(dialog);
  708.     XtPopup(XtParent(dialog), XtGrabNone);
  709.  
  710.     /* while the user hasn't provided an answer, simulate XtMainLoop.
  711.      * The answer changes as soon as the user selects one of the
  712.      * buttons and the callback routine changes its value.  Don't
  713.      * break loop until XtPending() also returns False to assure
  714.      * widget destruction.
  715.      */
  716.     while (answer == 0 || XtAppPending(app))
  717.         XtAppProcessEvent(app, XtIMAll);
  718.     return answer;
  719. }
  720.  
  721. /* response() --The user made some sort of response to the
  722.  * question posed in AskUser().  Set the answer (client_data)
  723.  * accordingly and destroy the dialog.
  724.  */
  725. void
  726. response(w, answer, reason)
  727. Widget w;
  728. int *answer;
  729. XmAnyCallbackStruct *reason;
  730. {
  731.     switch (reason->reason) {
  732.         case XmCR_OK:
  733.             *answer = YES;
  734.             break;
  735.         case XmCR_CANCEL:
  736.             *answer = NO;
  737.             break;
  738.         default:
  739.             *answer = NO;
  740.             return;
  741.     }
  742. }
  743.  
  744.  
  745.  
  746. If you aren't running a window manager that acknowledges this hint, then you
  747. may have to grab the pointer (and keyboard) yourself to make sure the user
  748. doesn't interact with any other widget.  Change the grab flag in XtPopup to
  749. XtGrabExclusive, and XtRemoveGrab(XtParent(w)) to the response() function.
  750.  
  751.  
  752. -----------------------------------------------------------------------------
  753. Subject: 84) TOPIC: MEMORY AND SPEED
  754.  
  755. -----------------------------------------------------------------------------
  756. Subject: 85)  Why does my application grow in size?
  757.